#include <iostream>
#include <string>
#include <vector>
#include <unistd.h>
#include <fcntl.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <functional>
#include <ctime>
using work_t = std::function<void()>;

#include "processpool.hpp"
#include "Task.hpp"
#include "Channel.hpp"

enum
{
    OK = 0,
    FORKERR,
    USAGEERR,
    PIPEERR,
    WRITERR,
    READERR
};
void Usage(std::string str)
{
    std::cout << "Usage，" << str << " process-num" << std::endl;
}
int main(int argc, char *argv[])
{
    if (argc != 2)
    {
        Usage(argv[0]);
        exit(USAGEERR);
    }
    int num = std::stoi(argv[1]); // 需要创建的进程个数
    std::vector<Channel> ch;
    for (int i = 0; i < num; i++)
    {
        // 创建匿名管道，再被子进程继承，父子进程看到同一份资源
        int pipefd[2] = {0};
        int n = ::pipe(pipefd);
        if (n == 0) // 管道创建成功
        {
            pid_t id = fork(); // 创建子进程，子进程继承父进程的读写端
            if (id > 0)        // 父进程
            {
                ::close(pipefd[0]);      // 父进程关闭读端
                //ch.push_back(pipefd[1],id); // 管理文件描述符
                ch.push_back(Channel(pipefd[1],id));

                // 派发任务
                int taski = gtask.DispatchTask(); // 随机派发任务
                ssize_t n = ::write(pipefd[1], &taski, sizeof(taski));
                if (n > 0) // 写入成功
                {
                    //std::cout << "派发任务成功" << std::endl;
                }
                else if(n == 0)
                {
                    std::cout << "子进程读端退出，me too" << std::endl;
                }
                else
                {
                    std::cout << "读错误" << std::endl;
                    exit(WRITERR);
                }
                // int wid = ::waitpid(id,nullptr,WNOHANG);
                // if(wid < 0) std::cout << "等待子进程失败" << std::endl;
                // else if(wid > 0) std::cout << "等待子进程成功" << std::endl;
            }
            else if (id == 0) // 子进程
            {
                ::close(pipefd[1]); // 子进程关闭写端，父进程派发任务，子进程来执行任务
                while(true)
                {
                    int taski;
                    ssize_t n = ::read(pipefd[0], &taski, sizeof(taski));
                    if (n == sizeof(taski))
                    {
                        gtask.Execute(taski);
                    }
                    else if (n == 0)
                    {
                        std::cout << "pid: " << getpid() << " quit..." << std::endl;
                        break;
                    }
                    else
                    {
                    }
                }
                ::exit(0);
            }
            else
            {
                std::cout << "创建子进程失败" << std::endl;
                exit(FORKERR);
            }
        }
        else // 管道创建失败，错误码被设置
        {
            std::cout << "PIPEERR，err code : " << errno << std::endl;
            ::exit(PIPEERR);
        }
        sleep(1);
    }
    // for(auto &channel : ch)//关闭打开的管道的写端
    // {
    //     channel.close();
    // }
    for (int i = ch.size() - 1; i >= 0; i--)
    {
        ch[i].close();
        pid_t wid = waitpid(ch[i].Getpid(),nullptr,0);
        if(wid > 0)
        {
            std::cout << "等待子进程成功" << std::endl;
        }
    }
    //sleep(100);
    return 0;
}